package com.zan.zanchat.common.common.interceptor;

import com.zan.zanchat.common.common.exception.HttpErrorEnum;
import com.zan.zanchat.common.user.service.LoginService;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
import java.util.Optional;

/**
 * @Author Zan
 * @Create 2024/3/14 16:00
 * @Description : token拦截器
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {

    public static final String HEADER_AUTHORIZATION = "Authorization";
    public static final String AUTHORIZATION_SCHEMA = "Bearer ";
    public static final String UID = "uid";

    @Resource
    private LoginService loginService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = getToken(request);
        Long uid = loginService.getValidUid(token);
        if (Objects.nonNull(uid)) {
            // 用户有登录态，登录成功
            request.setAttribute(UID, uid);
        } else {
            // 用户未登录 - 看看是不是public的
            boolean isPublicURI = isPublicURI(request);
            if (!isPublicURI) {
                // 不是public的接口，也就是需要登录才能访问 - 因此返回401
                HttpErrorEnum.ACCESS_DENIED.sendHttpError(response);
                return false;
            }
        }
        return true; // 放行
    }

    private boolean isPublicURI(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        String[] split = requestURI.split("/");
        boolean isPublicURI = split.length > 3 && "public".equals(split[3]); // 最前面的空白是0
        return isPublicURI;
    }

    private String getToken(HttpServletRequest request) {
        // 获取请求头
        String authorizationHeader = request.getHeader(HEADER_AUTHORIZATION);
        return Optional.ofNullable(authorizationHeader)
                .filter(header -> header.startsWith(AUTHORIZATION_SCHEMA))
                .map(header -> header.replaceFirst(AUTHORIZATION_SCHEMA, ""))
                .orElse(null);
    }

}
